<?php
/**
 * Created by PhpStorm.
 * User: chniccs
 * Date: 2019-11-14
 * Time: 15:05
 */

namespace app\admin\controller;


use app\constant\ActivesConst;
use app\constant\DistriConst;
use app\constant\OrderConst;
use app\constant\RewardConst;
use app\helper\OrderHelper;
use app\helper\VipHelper;
use app\helper\WxHelper;
use app\libs\Utils;
use app\model\AdminDistridetail;
use app\model\AdminOrder;
use app\model\AdminOrderItem;
use app\model\AdminOrderPayFailed;
use app\model\AdminReward;
use app\model\AdminTenant;
use EasyWeChat\Factory;
use EasyWeChat\Kernel\Exceptions\Exception;
use think\Db;
use think\facade\Log;

class Notify extends Base
{

    /**
     * 微信支付异步通知接收接口
     */
    public function wxPayNotify()
    {
        $data = file_get_contents("php://input");
        $objectxml = (array)simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA); //将微信返回的XML 转换成数组
        $attachStr = $objectxml['attach'];
        $attachData = json_decode($attachStr,true);
        $tid = $attachData['tid'];
        $model = AdminTenant::get($tid, null, true);
        if ($model) {
            $result = WxHelper::getWxPayConfig($model->id, $this->request);
            if ($result['done']) {
                $config = $result['config'];
                $app = Factory::payment($config);
                try {
                    $response = $app->handlePaidNotify(function ($message, $fail) use ($attachData, $tid) {
                        //目前两种订单处理都是一样的
                        if ($attachData['order_type'] == OrderConst::TYPE_VIP) {
                            return $this->opOrder($tid, $message, $fail);
                        } else if ($attachData['order_type'] == OrderConst::TYPE_GOODS) {
                            return $this->opOrder($tid, $message, $fail);
                        }
                        return $fail('通信失败，请稍后再通知我');
                    });
                    return $response->send();
                } catch (Exception $e) {
                    Log::write('订单支付失败' . $e->getMessage(), 'error');
                }
            }
        }
        //结果为FAIL，会继续回调
        $return['return_code'] = 'FAIL';
        $return['return_msg'] = 'OK';
        return $this->arrayToxml($return);
    }

    private function opOrder($tid, $message, $fail)
    {
        Db::startTrans();
        try {
            // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
            $var = explode("_", $message['out_trade_no']);
            //TODO 判断订单类型，现在有VIP会员订单和商品订单

            //商品订单的处理
            $orderid = $var[0];
            $orderModel = AdminOrder::get($orderid);
            if (!$orderModel || $orderModel->pay_status === OrderConst::PAY_STATUS_PAID_ONLINE) { // 如果订单不存在 或者 订单已经支付过了
                $fail('OK');
                return true; // 告诉微信，我已经处理完了，订单没找到，别再通知我了
            }
            ///////////// <- 建议在这里调用微信的【订单查询】接口查一下该笔订单的情况，确认是已经支付 /////////////

            if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态，不代表支付状态
                // 用户是否支付成功
                if ($message['result_code'] === 'SUCCESS') {
                    $orderModel->setAttr('pay_time', new \DateTime());
                    $orderModel->setAttr('pay_status', OrderConst::PAY_STATUS_PAID_ONLINE);
                    $orderModel->setAttr('outer_trade_no', $message['out_trade_no']);
                    $affected = $orderModel->allowField(true)->save();
                    if($orderModel->goods_type==ActivesConst::ACTIVE_TYPE_VIP){
                        //如果是VIP会员订单
                        $opVipDone = $this->opVipOrder($orderModel->id,$orderModel->tid,$orderModel->uid);
                        if(!$opVipDone){
                            throw new \Exception('处理续期失败');
                        }
                    }

                    if ($affected) {
                        //修改分销记录状态
                        (new AdminDistridetail())
                            ->where(['tid' => $tid, 'order_id' => $orderid])
                            ->update(['status' => DistriConst::STATUS_PAID]);
                        //添加推广赏金处理
                        if (!Utils::isEmpty($orderModel->invid)) {
                            (new AdminReward())
                                ->where(['tid' => $tid, 'order_id' => $orderModel->id])
                                ->update(['status' => RewardConst::STATUS_PAID]);
                        }
                        $fail('OK');
                    } else {
                        AdminOrderPayFailed::create(['order_id' => $orderid, 'out_trade_no' => $message['out_trade_no'], 'content' => json_encode($message), 'type' => 0,'order_type'=>OrderConst::TYPE_GOODS]);
                    }
                } elseif ($message['result_code'] === 'FAIL') {
                    $orderModel->setAttr('pay_status', OrderConst::PAY_STATUS_PAID_FAILED_ONLINE);
                    $orderModel->setAttr('outer_trade_no', $message['out_trade_no']);
                    $affected = $orderModel->allowField(true)->save();
                    if ($affected) {
                        $fail('OK');
                    } else {
                        AdminOrderPayFailed::create(['order_id' => $orderid, 'out_trade_no' => $message['out_trade_no'], 'content' => json_encode($message), 'type' => 0,'order_type'=>OrderConst::TYPE_GOODS]);
                    }
                }
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            Log::write('订单支付失败' . $message['out_trade_no'] . $e->getMessage(), 'error');
        }
        return true;
    }
    //处理VIP续期
    private function opVipOrder($orderId,$tid,$uid){
        $orderItem = AdminOrderItem::get(['tid'=>$tid,'order_id'=>$orderId]);
        if(!$orderItem){
            return false;
        }
        return VipHelper::addVipTime($uid,((int)($orderItem->sku_attach))*60*60*24);
    }

    /**
     * 微信退款异步通知接口
     */
    public function wxRefundNotify()
    {
        $data = file_get_contents("php://input");
        $objectxml = (array)simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA); //将微信返回的XML 转换成数组
        $gzhAppid = $objectxml['appid'];
        $model = AdminTenant::get(['gzh_appid' => $gzhAppid]);
        if ($model) {
            $result = WxHelper::getWxPayConfig($model->id, $this->request);
            if ($result['done']) {
                $config = $result['config'];
                $app = Factory::payment($config);
                try {
                    $response = $app->handleRefundedNotify(function ($message, $reqInfo, $fail) {
                        // 其中 $message['req_info'] 获取到的是加密信息
                        // $reqInfo 为 message['req_info'] 解密后的信息
                        if ($message['return_code'] == 'SUCCESS') {
//                            refund_id
                            $id = $reqInfo['out_refund_no'];
                            $orderModel = AdminOrder::get($id);
                            if (!$orderModel || $orderModel->pay_status === OrderConst::PAY_STATUS_REFUNDED) { // 如果订单不存在 或者 订单已经退款了
                                $fail('OK');
                                return true; // 告诉微信，我已经处理完了，订单没找到，别再通知我了
                            }
                            if ($reqInfo['refund_status'] == 'SUCCESS') {
                                //退款成功
                                $done = (new OrderHelper())->refund($id, OrderConst::REFUND_TO_ORIGINAL, $reqInfo['refund_id'], $reqInfo['success_time']);
                                if ($done) {
                                    $fail('OK');
                                }
                            } else if ($reqInfo['refund_status'] == 'CHANGE') {
                                //退款异常
                                $fail('OK');
                                Log::write('订单退款失败' . json_encode($reqInfo), 'error');
                            }
                        } else {
                            Log::write('订单退款失败' . $message['return_msg'], 'error');
                            return $fail('通信失败，请过一会再通知我');
                        }
                        return true; // 返回 true 告诉微信“我已处理完成”
                    });
                    return $response;
                } catch (Exception $e) {
                    Log::write('订单退款失败' . $e->getMessage(), 'error');
                }
            }
        }
        //结果为FAIL，会继续回调
        $return['return_code'] = 'FAIL';
        $return['return_msg'] = 'OK';
        return $this->arrayToxml($return);
    }

    public function arrayToxml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        return $xml .= "</xml>";
    }
}